﻿using System;
using System.Collections.Generic;
using System.Deployment.Application;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Threading;
using System.Xml.Linq;

namespace D3StatsClient.Model
{
    public class XMLStatsProvider : IStatsProvider
    {
        private XDocument xmlStats;
        private Guid _currentSession = Guid.Empty;
        private string filePath = string.Empty;
        private string fileName = string.Empty;
        Dispatcher _dispatcher;

        public XMLStatsProvider(Dispatcher dispatcher)
        {
            this._dispatcher = dispatcher;
        }

        public XDocument XMLData
        {
            get
            {
                return xmlStats;
            }
            set
            {
                xmlStats = value;
            }
        }

        public void OpenConnection(string name)
        {
            _currentSession = Guid.NewGuid();

            initFile();

            if (!string.IsNullOrEmpty(name))
            {
                xmlStats.Element("items").Add(
                    new XAttribute("sessionname", name));
            }

            xmlStats.Element("items").Add(
                    new XAttribute("sessionid", _currentSession.ToString("N")));

            this.SetStartTime(DateTime.Now);
        }

        private void initFile()
        {
            FileName = string.Format("session_{0}.stats", _currentSession.ToString("N"));

            try
            {
                if (!Directory.Exists(filePath))
                {
                    Directory.CreateDirectory(FilePath);
                }

                File.Create(Path.Combine(FilePath, FileName)).Close();
            }
            catch (Exception ex)
            {
                Logging.Logger.Log(ex.Message);
            }

            xmlStats = new XDocument();
            
            this.EnsureRootNode();
        }

        public void RecordDrop(D3TrackerItem stats)
        {
            if (_currentSession == Guid.Empty)
            {
                throw new Exception("You must start a session before writing item data.");
            }

            XElement item = new XElement("item",
                    new XElement("name", stats.Name),
                    new XElement("quality", stats.Quality),
                    new XElement("id", stats.ID),
                    new XElement("location", stats.Location),
                    new XElement("level", stats.ItemLevel),
                    new XElement("magicfind", stats.MagicFind),
                    new XElement("timestamp", stats.Time),
                    new XElement("server", stats.Server),
                    new XElement("IsPickedUp", stats.IsPickedUp),
                    new XElement("ItemLink", stats.ItemLink));

            XElement root = xmlStats.Element("items");
            root.Add(item);

        }

        public void RecordPlayedInfo(XElement e)
        {
            if (xmlStats.Element("items").Element("player") == null)
            {
                xmlStats.Element("items").Add(new XElement("player"));
            }

            if (e != null)
            {
                xmlStats.Element("items").Element("player").Add(e);
            }
        }

        private void EnsureRootNode()
        {
            if (xmlStats.Elements("items").Count() == 0)
            {
                xmlStats.Add(new XElement("items"));
            }
        }

        public void CloseConnection(TimeSpan played)
        {
            this.SetEndTime(DateTime.Now);

            if (xmlStats.Element("items").Attribute("played") != null)
            {
                var previousPlayed = TimeSpan.Parse(xmlStats.Element("items").Attribute("played").Value);

                xmlStats.Element("items").Attribute("played").Value = (previousPlayed + played).ToString();
            }
            else
            {
                xmlStats.Element("items").Add(new XAttribute("played", played.ToString()));
            }
            

            xmlStats.Save(Path.Combine(FilePath, FileName));
            
        }


        public bool ContainsDrop(int uniqueId)
        {
            var result = from i in xmlStats.Descendants("item") where i.Element("id").Value == uniqueId.ToString() select i;

            return result.Count() > 0;
        }

        private void SetStartTime(DateTime time)
        {
            xmlStats.Element("items").Add(new XAttribute("starttime", time));
        }

        private void SetEndTime(DateTime time)
        {
            if (xmlStats.Element("items").Attribute("endtime") != null)
            {
                xmlStats.Element("items").Attribute("endtime").Value = time.ToString();
            }
            else
            {
                xmlStats.Element("items").Add(new XAttribute("endtime", time));
            }
        }

        public string FilePath
        {
            get
            {
                if (ApplicationDeployment.IsNetworkDeployed)
                {
                    return string.Format("{0}\\{1}", ApplicationDeployment.CurrentDeployment.DataDirectory, Properties.Settings.Default.XMLStatsContainer);
                }

                return string.Format("{0}", AppDomain.CurrentDomain.BaseDirectory + Properties.Settings.Default.XMLStatsContainer);
            }
        }

        public string FileName
        {
            get
            {
                return fileName;
            }
            set
            {
                fileName = value;
            }
        }

        public void ResumeSession()
        {
            //Remove the endtime since we are resuming this session

            if (xmlStats.Element("items").Attribute("endtime") != null)
            {
                xmlStats.Element("items").Attribute("endtime").Remove();
            }

            _currentSession = new Guid(xmlStats.Element("items").Attribute("sessionid").Value);
        }

        private XElement GetItemById(int id)
        {
            var result = (from i in xmlStats.Descendants("item") where i.Element("id").Value == id.ToString() select i).FirstOrDefault();

            return result;
        }
 

        public D3TrackerItem GetItem(int uniqueId)
        {
            var result = GetItemById(uniqueId);

            D3TrackerItem item = new D3TrackerItem(result.ToString(SaveOptions.DisableFormatting));
            
            return item;
        }


        public bool UpdateItem(D3TrackerItem item)
        {
            XElement xItem = this.GetItemById(item.ID);

            if (xItem != null)
            {
                xItem.Remove();

                this.RecordDrop(item);
                return true;
            }

            return false;

        }

    }
}
